package com.hosever.coreTest;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import com.hosever.model.SpecialUser;
import com.hosever.model.User;

/**
 * 类测试
 * @author Sever
 *
 */
public class ClassTest {

	@SuppressWarnings({ "rawtypes", "unused" })
	public static void main(String[] args) {
		try {
			SpecialUser su = newEntity(SpecialUser.class);
			User u = castObject(su, User.class);

			Class<SpecialUser> clzz = SpecialUser.class;
			
			//TODO 无参构造器
			Constructor<SpecialUser> con = clzz.getConstructor();

			//TODO 带参构造器
			Class[] parameterTypes = { String.class,String.class,int.class };
			Constructor<SpecialUser> con2 = clzz.getConstructor(parameterTypes);
			SpecialUser su2 = con2.newInstance("a","a",1);
//			System.out.println(su2.getName());
			
			//TODO 反射执行单个方法（无参）
			/**
			 * getMethod获取共有方法，getDeclaredMethod是获取自身声明方法（不包括超类）
			 * 举一反三 
			 * getMethods 和 getDeclaredMethods
			 * getFields 和 getDeclaredFields
			 * getConstructors 和 getDeclaredConstructors
			 * 异曲同工
			 */
			Method getNameMethod = su2.getClass().getMethod("getName");
//			System.out.println(nameMethod.getName());
			Class<?> returnType = getNameMethod.getReturnType();
			String name = (String) getNameMethod.invoke(su2);//执行方法，有参数则返回
//			System.out.println(name);
			
			//TODO 反射执行单个方法（带参）
			Class[] methodParameterTypes = { String.class };
			Method setNameMethod = su2.getClass().getMethod("setName",methodParameterTypes);
//			System.out.println(nameMethod.getName());
			setNameMethod.invoke(su2,"b");
//			System.out.println(su2.getName());
			
			//TODO 反射获取所有方法
			Method[] methods = su2.getClass().getDeclaredMethods();
//			for(Method method : methods){
//				Class<?>[] pts = method.getParameterTypes();//获取方法的参数的类
//				String parameterString = "";
//				for(Class<?> pt : pts){
//					parameterString += pt.getName()+",";
//				}
//				if(parameterString.length()>0){
//					parameterString = parameterString.substring(0, parameterString.length()-1);
//				}
//				System.out.println(method.getName()+"("+parameterString+")");
//			}
			
			//TODO 反射获取域（属性）
			Field[] fields = su2.getClass().getDeclaredFields();
			for(Field f : fields){
				Type type =f.getGenericType();//属性声明的类型
				Class<?> typeClass = f.getType();
				Annotation[] as = f.getAnnotations();//获取注解，也就是@……
				System.out.println(typeClass.getName()+" "+f.getName());//只获取当前类的属性，不获取超类的属性
			}
			
			
			

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

	}

	/**
	 * class类创建对象（空参构造器）
	 * 
	 * @param clazz
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public static <T> T newEntity(Class<T> clazz)
			throws InstantiationException, IllegalAccessException {
		T t = clazz.newInstance();
		return t;
	}

	/**
	 * 构造器创建对象
	 * 
	 * @param clazz
	 * @return
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 */
	public static <T> T newEntity2(Class<T> clazz, Object... initargs)
			throws IllegalArgumentException, InstantiationException,
			IllegalAccessException, InvocationTargetException,
			SecurityException, NoSuchMethodException {
		Constructor<T> c = clazz.getConstructor((Class<?>[]) initargs);
		T t = (T) c.newInstance(initargs);
		return t;
	}

	/**
	 * class类强转
	 * 
	 * @param clazz
	 * @return
	 */
	public static <T> T castObject(Object obj, Class<T> clazz) {
		T t;
		try {
			t = clazz.cast(obj);
			return t;
		} catch (ClassCastException e) {
			e.printStackTrace();
		}

		return null;
	}

}
